package com.zjw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjw.annotation.domain.vo.*;
import com.zjw.constants.SystemConstants;
import com.zjw.annotation.domain.ResponseResult;
import com.zjw.annotation.domain.dto.SaveArticleDto;
import com.zjw.annotation.domain.dto.UpdateArticleDto;
import com.zjw.annotation.domain.entity.Tag;
import com.zjw.enums.AppHttpCodeEnum;
import com.zjw.mapper.ArticleMapper;
import com.zjw.annotation.domain.entity.Article;
import com.zjw.service.ArticleService;
import com.zjw.service.CategoryService;
import com.zjw.service.TagService;
import com.zjw.utils.BeanCopyUtils;
import com.zjw.utils.RedisCache;
import io.jsonwebtoken.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 文章表(Article)表服务实现类
 *
 * @author makejava
 * @since 2023-12-11 16:40:42
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private TagService tagService;

    @Autowired
    private RedisCache redisCache;


    /**
     * 获取热门文章列表
     *
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getHotArticleList() {
        LambdaQueryWrapper<Article> wp = new LambdaQueryWrapper<>();
//        文章不能是草稿
        wp.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
//
        wp.orderByDesc(Article::getViewCount);

//        通过分页限制前10条， 第一页查10条
        IPage<Article> listPage = new Page(1, 10);
        List<Article> records = page(listPage, wp).getRecords();

//        TODO 判断文章标签是否被禁用
//        VO
        List<HotArticleVo> res = BeanCopyUtils.copyList(records, HotArticleVo.class);


        return ResponseResult.okResult(res);
    }

    /**
     * 文章列表
     *
     * @param pageNum    页码
     * @param pageSize   页面大小
     * @param categoryId 类别 ID
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();

//        定义wrapper
//        如果第一个参数条件成立，那么就加上后面两个参数，否则无效
        wrapper.eq(Objects.nonNull(categoryId) && categoryId > 0, Article::getCategoryId, categoryId);
//        文章状态必须是已经发布
        wrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);

//        是否置顶，只需要对isTop字段排序即可，因为置顶是1，非置顶是0
        wrapper.orderByAsc(Article::getIsTop);

//        分页对象；先定义和配置MP配置类，添加分页插件
        IPage<Article> page = new Page(pageNum, pageSize);
//        查询
        page(page, wrapper);


        List<Article> records = page.getRecords();
//        每一个的categoryName字段还没有正确值; 通过每个id进行查询对categoryName进行赋值
        records.stream().forEach(e -> {
            e.setCategoryName(categoryService.getById(e.getCategoryId()).getName());
        });

        List<ArticleListVo> resList = BeanCopyUtils.copyList(records, ArticleListVo.class);


        return ResponseResult.okResult(new PageVo(resList, page.getTotal()));
    }

    /**
     * 按 ID 获取文章
     *
     * @param id
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getArticleById(Long id) {

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getId, id);

        Article one = getOne(wrapper);
        if (Objects.isNull(one)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ARTICLE_NO_EXIST);
        }
//        查询并设置分类名称
        one.setCategoryName(categoryService.getById(one.getCategoryId()).getName());
        ArticleVo res = BeanCopyUtils.copy(one, ArticleVo.class);

        return ResponseResult.okResult(res);
    }

    /**
     * 更新查看次数
     *
     * @param id 编号
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult updateViewCount(Long id) {
//        查询对应文章实体类
//        Article article = getById(id);
//        article.setViewCount(article.getViewCount() + 1);
//        updateById(article);

        redisCache.incrementKey(SystemConstants.REDIS_VIEW_COUNT_KEY, id.toString());
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult saveArticle(SaveArticleDto saveArticleDto) {

//        创建文章对象
        Article article = BeanCopyUtils.copy(saveArticleDto, Article.class);

//        插入文章对象
        save(article);

//        更新文章和标签的一对多关系
        saveArticleDto.getTags().stream().forEach(t -> {
            long tId = Long.parseLong(t);
            tagService.addArticleTag(article.getId(), tId);
        });

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getAllArticleList(Long pageNum, Long pageSize, String title, String summary) {

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        if (title != null && Strings.hasText(title)) {
//            封装标题模糊查询
            wrapper.like(Article::getTitle, title);
        }
        if (summary != null && Strings.hasText(summary)) {
//            封装标题模糊查询
            wrapper.like(Article::getSummary, summary);
        }

        Page<Article> page = new Page(pageNum, pageSize);
        page(page, wrapper);

        List<Article> rawList = page.getRecords();
        List<AllArticleListVo> res = BeanCopyUtils.copyList(rawList, AllArticleListVo.class);
        return ResponseResult.okResult(new PageVo(res, page.getTotal()));
    }

    /**
     * 按 ID 获取编辑文章
     *
     * @param id 编号
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getEditArticleById(Long id) {
//        查询指定id文章并返回
        Article art = getById(id);

//        拷贝
        EditArticleVo res = BeanCopyUtils.copy(art, EditArticleVo.class);

//        查询当前文章的标签信息
        List<Tag> tags = tagService.getTagsByArticleId(id);
        List<String> resTags = tags.stream().map(t -> t.getId().toString()).collect(Collectors.toList());

        res.setTags(resTags);

        return ResponseResult.okResult(res);
    }


    /**
     * 更新文章
     *
     * @param updateArticleDto 更新文章 DTO
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult updateArticle(UpdateArticleDto updateArticleDto) {

//        创建文章
        Article article = BeanCopyUtils.copy(updateArticleDto, Article.class);

        //        更新文章
        if (!updateById(article)) {
//            更新失败
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_INVALID_CHECK);
        }

//        更新标签
//        先删除标签
        tagService.deleteTags(article.getId());
//        更新文章和标签的一对多关系
        updateArticleDto.getTags().stream().forEach(t -> {
            long tId = Long.parseLong(t);
            tagService.addArticleTag(article.getId(), tId);
        });


        return ResponseResult.okResult();
    }

    /**
     * 删除文章列表
     *
     * @param idList ID 列表
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult deleteArticleList(List<Long> idList) {
        idList.stream().forEach(id->{
//            删除指定 id文章
            removeById(id);
//            删除指定 id文章标签
            tagService.deleteTags(id);
        });
        return ResponseResult.okResult();
    }
}

